﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
using System.IO;



//  в данные диспетчеру необходимо добавить куда загружать объект (в отдельный процесс, в текущий домен в текущем процессе, в отдельный домен в текущем процессе )  тогда это не просто список паспортов
//  2. сценарий запуска процесса (типа 1. востановить объект 2. запустить некоторые его функции (инициализация и запуск) хотя этот сценарий можно запускать во время востановления (собственной функцией востановления)
//  



namespace конфигуратор
{


    // сценарий загрузки       рпрпрпр
    //1. этап восстановление объекта и его данных
    // 2 этап - восстановление связей объектов между собой - Запуск Метода ВосстановитьСвязи() для каждого объекта
    // 3 этап - запуск сущностей Вызовом Метода Пуск()

 

    public class Диспетчер       
    {
        public static Паспорт ПаспортКорневогоДиспетчера ;
        
        public Паспорт СвойПаспорт = new Паспорт();
        public bool СохранятьсяПриВыходе { get; set; }
        public bool СохранятьОбъектыПриВыходе { get; set; }
        public bool ВосстанавливатьОбъектыПриВосстановлении { get; set; }

        public ObservableCollection<Паспорт> Хранилище = new ObservableCollection<Паспорт>();

        public Диспетчер ( )
        {
            ЗаполнитьПаспортДиспетчераПоУмолчанию();
        }

        public void ЗаполнитьПаспортДиспетчераПоУмолчанию ()
        {
            СвойПаспорт.Объект = this;
            СвойПаспорт.СвойСохранительВосстановитель = true;
            СвойПаспорт.ИмяМетодаСохранителя = "Сохранить_хранилище_на_диск";
            СвойПаспорт.ИмяМетодаВосстановителя = "Восстановить_хранилище_с_диска";
            //СвойПаспорт.АдресСпячки = @"e:\диспетчер";
            СвойПаспорт.Имя =СвойПаспорт.УН;
        }



        // операции с объектами
        public  Результат ДобавитьНовыйОбъект ( Паспорт новыйПаспорт )
        {
            var рез = new Результат();

            if ( НайтиПервыйПаспортПоИмени( новыйПаспорт.Имя ) != null )
            {
                рез.Успешно = false;
                рез.ТекстОшибки = "такое имя уже существует";
                return рез;
            }
            Хранилище.Add( новыйПаспорт );

            рез.Отчет = "добавлен паспорт в хранилище";

            return рез;

        }
      
      

        public Паспорт НайтиПервыйПаспортПоИмени (  string имя )
        {
            try
            {
                return Хранилище.First( паспорт => имя == паспорт.Имя );
            }
            catch
            {
                return null;
            }
        }


        public void УдалитьИзХранилищаБезСохранения ( Паспорт удаляемыйПаспорт )
        {
            Хранилище.Remove( удаляемыйПаспорт );

        }

        public void ОчиститьХранилищеБезСохранения ()
        {
            Хранилище.Clear();
        }

        public void СохранитьХранилищеНаДиск ( string файл )
        {
            var mystream = new FileStream( СвойПаспорт.Файл + ".диспетчер", FileMode.Create );
                var xml = new XmlSerializer( typeof( Диспетчер ) );
                xml.Serialize( mystream, this );
            mystream.Close();
        }

        public static Диспетчер ВосстановитьХранилищеСДиска ( string файл )   // восстановить диспетчер(результат) из файла(параметр:имя файла) на диске
        {
            //востановить паспорта  - все объекты не активны - не загружены в память
            var диспетчер = ( Диспетчер ) Паспорт.ВосcтановитьИзXml( файл, typeof( Диспетчер ) );
            диспетчер.СвойПаспорт.Объект = диспетчер;

            if ( диспетчер.ВосстанавливатьОбъектыПриВосстановлении ) диспетчер.ВосстановитьОбъекты();

            диспетчер.УстановитьСвязи();

            return диспетчер;
        }

        public void СохранитьОбъектыНаДиск ()
        {
            foreach ( var паспорт in Хранилище )
            {
                    паспорт.СохранитьСостояниеОбъекта();
            }
        }

        public void ВосстановитьОбъекты ()
        {
            foreach ( Паспорт паспорт in Хранилище )
            {
                try
                {
                    паспорт.ВосстановитьОбъект();
                }
                catch { }
            }
        }

        public void УстановитьСвязи ()
        {
            foreach ( Паспорт паспорт in Хранилище )
            {
                try
                {
                    dynamic o = паспорт.Объект;
                    o.УстановитьСвязь();
                }
                catch { }
            }
        }

        public void РазорватьСвязи ()
        {
            foreach ( Паспорт паспорт in Хранилище )
            {
                try
                {
                    dynamic o = паспорт.Объект;
                    o.РазорватьСвязь();
                }
                catch { }
            }
        }

        //public static object НайтиОбъект ( string имяДиспетчера, string имяОбъекта )
        //{
        //    var дис = Диспетчер.Найти( имяДиспетчера);

        //    if ( имяОбъекта == дис.СвойПаспорт.Имя ) return дис;
        //    try
        //    {
        //        return дис.Хранилище.First( паспорт => имяОбъекта == паспорт.Имя ).Объект;
        //    }
        //    catch
        //    {
        //        return null;
        //    }
        //}

        //public static object НайтиОбъект ( string имяОбъекта )
        //{
        //    var дис = СловарьДиспетчеров.GetEnumerator().Current.Value;

        //    if ( имяОбъекта == дис.СвойПаспорт.Имя ) return СловарьДиспетчеров;
        //    try
        //    {
        //        return дис.Хранилище.First( паспорт => имяОбъекта == паспорт.Имя ).Объект;
        //    }
        //    catch
        //    {
        //        return null;
        //    }
        //}

    }
}